package Network

import (
	"SQL/myDB"
	"database/sql"
	"encoding/json"
	"fmt"
	"logs"
	"regexp"
	"sort"
	"token"
)

type dy_judge map[string]interface{}

var groupCustomKey map[string]bool = map[string]bool{
	"公告": true, "类型": true, "地址": true, "网站": true, "群介绍": true}
var userCustomKey map[string]bool = map[string]bool{
	"真实姓名": true, "公司": true, "职位": true, "部门": true, "地址": true,
	"电子邮箱": true, "网站": true, "生日": true, "备注": true}
var errAssertMsg string = "type assert failed"
var defaultIconURL string = "/icon/default.ico"

func (j dy_judge) judgeID(key string, args ...interface{}) (code int, msg string, ID string) {
	var ok bool
	if len(args) == 0 {
		ID, ok = j[key].(string)
	} else if len(args) == 1 {
		ID, ok = args[0].(string)
	} else {
		return errInvalidID, "too many IDs", ""
	}
	if !ok {
		return errAssertType, "ID " + errAssertMsg, ""
	}
	ok, err := regexp.MatchString("^[0-9]{5,16}$", ID)
	if err != nil {
		return errInvalidID, err.Error(), ""
	}
	if !ok {
		return errInvalidID, "ID不合法", ""
	}
	if key == "groupID" {
		code, msg = IsGroupID(ID)
		return code, msg, ID
	}
	return Success, "", ID
}
func (j dy_judge) judgeMemberIDs(key string) (code int, msg string, memberID []string) {
	IDs, ok := j[key].([]interface{})
	if !ok {
		return errAssertType, "MemberIDs " + errAssertMsg, nil
	}
	return judgeMemberIDs(IDs)
}
func (j dy_judge) judgeNickname(key string) (code int, msg string, nickname string) {
	nickname, ok := j[key].(string)
	if !ok {
		return errAssertType, "Nickname " + errAssertMsg, ""
	}
	if len([]rune(nickname)) > 15 || len(nickname) == 0 {
		logs.Print("超长的nickname长度：", len(nickname))
		return errInvalidNickname, "nickname为空或过长度超过15", ""
	}
	return Success, "", nickname
}
func (j dy_judge) judgeIconURL(key string) (code int, msg string, iconURL string) {
	iconURL, ok := j[key].(string)
	if !ok {
		return errAssertType, "IconURL " + errAssertMsg, ""
	}
	return Success, "", iconURL
}

func (j dy_judge) judgeCustom(customType string) (code int, msg string, custom []byte) {
	var customKey map[string]bool
	var lenLimit int
	if customType == "group" {
		customKey = groupCustomKey
		lenLimit = 100
	} else if customType == "user" {
		customKey = userCustomKey
		lenLimit = 50
	} else {
		return errNoPermission, "custom key should be group or user", nil
	}
	for key, val := range j {
		if !customKey[key] {
			return errInvalidCustomInfo, key + " 不在" + customType + "自定义属性列表中", nil
		}
		value, ok := val.(string)
		if !ok {
			return errAssertType, "Custom key " + errAssertMsg, nil
		}
		if len([]rune(value)) > lenLimit || len(value) == 0 {
			return errInvalidCustomInfo, "属性值的为空或长度超过" + fmt.Sprint(lenLimit), nil
		}
	}
	custom, err := json.Marshal(j)
	if err != nil {
		return errMarshalJSONFailed, "", nil
	}
	return Success, "", custom
}
func (j dy_judge) judgePageIndex(key string) (code int, msg string, pageIndex int) {
	Index, ok := j[key].(float64)
	if !ok {
		return errAssertType, "PageIndex " + errAssertMsg, 0
	}
	pageIndex = int(Index)
	if pageIndex < 0 {
		return errInvalidPageIndex, "pageIndex 不能小于0", 0
	}
	return Success, "", pageIndex
}
func (j dy_judge) judgePageSize(key string) (code int, msg string, pageSize int) {
	Size, ok := j[key].(float64)
	if !ok {
		return errAssertType, "PageSize " + errAssertMsg, 0
	}
	pageSize = int(Size)
	if pageSize > 50 {
		return errInvalidPageSize, "pageSize 不应大于50", 0
	}
	return Success, "", pageSize
}
func IsGroupID(groupID string) (int, string) {
	rows, err := myDB.QuerySql("select isUser from objects where id=$1", groupID)
	if err != nil {
		return errDBQueryFailed, err.Error()
	}
	defer rows.Close()
	if !rows.Next() {
		return errNotExistID, "groupID " + groupID + " not exist"
	}
	var isUser bool
	err = rows.Scan(&isUser)
	if err != nil {
		return errRowsScan, err.Error()
	}
	if isUser {
		return errInvalidID, groupID + " is user"
	}
	return Success, ""
}

func IsUserIDInMemberID(userID string, memberID []string) bool {
	for _, val := range memberID {
		if val == userID {
			return true
		}
	}
	return false
}
func judgeMemberIDs(IDs []interface{}) (code int, msg string, memberIDs []string) {
	db := openDB()
	defer closeDB(db)

	memberIDs = make([]string, 0)
	for _, val := range IDs {
		var memberID string
		code, msg, memberID = dy_judge{}.judgeID("memberID", val)
		if code != Success {
			return
		}
		memberIDs = append(memberIDs, memberID)
	}

	stmt, err := db.Prepare("select isUser from objects where id=$1")
	if err != nil {
		code = errOpenDB
		msg = err.Error()
		return
	}
	defer stmt.Close()

	sort.Strings(memberIDs)
	lastMemberID := ""
	for _, val := range memberIDs {
		if val == lastMemberID {
			return errInvalidID, "memberIDs 有多个相同的memberID", nil
		}
		lastMemberID = val
		code, msg = judgeMember(stmt, val)
		if code != Success {
			return
		}
	}
	return Success, "", memberIDs
}

func judgeMember(stmt *sql.Stmt, memberID string) (code int, msg string) {
	rows, err := stmt.Query(memberID)
	if err != nil {
		code = errDBExecFailed
		msg = err.Error()
		return
	}
	defer rows.Close()
	if !rows.Next() {
		code = errInvalidID
		msg = memberID + " is not exist"
		return
	}
	var isUser bool
	err = rows.Scan(&isUser)
	if err != nil {
		code = errRowsScan
		msg = err.Error()
		return
	}
	if !isUser {
		code = errInvalidID
		msg = memberID + " is not user"
		return
	}
	code = Success
	msg = ""
	return
}

//select count(*) from groups where owner = $1
func canCreateGroup(userID string) (code int, msg string) {
	rows, err := myDB.QuerySql("select count(*) from groups where owner = $1", userID)
	if err != nil {
		return errDBQueryFailed, err.Error()
	}
	defer rows.Close()
	var ownGroups int
	if !rows.Next() {
		return errDBQueryFailed, "rows have not next"
	}
	err = rows.Scan(&ownGroups)
	if err != nil {
		return errRowsScan, err.Error()
	}
	if ownGroups >= 5 {
		return errNoPermission, "每个人创建的不能超过5个"
	}
	return Success, ""
}

//select isManager from members where groupID = $1 and userID = $2
func IsGroupManager(userID string, groupID string) (code int, msg string) {
	rows, err := myDB.QuerySql("select isManager from members where groupID = $1 and userID = $2", groupID, userID)
	if err != nil {
		return errDBQueryFailed, err.Error()
	}
	defer rows.Close()
	var isManager bool
	if !rows.Next() {
		return errNoPermission, "user " + userID + "is not in group " + groupID
	}
	err = rows.Scan(&isManager)
	if err != nil {
		return errRowsScan, err.Error()
	}
	if !isManager {
		return errNoPermission, "user " + userID + " is not manager of group " + groupID
	}
	return Success, ""
}

func IsGroupMember(userID string, groupID string) (code int, msg string) {
	rows, err := myDB.QuerySql("select isManager from members where groupID = $1 and userID = $2", groupID, userID)
	if err != nil {
		return errDBQueryFailed, err.Error()
	}
	defer rows.Close()
	if !rows.Next() {
		return errInvalidID, "user " + userID + "is not member of group"
	}
	return Success, ""
}

func IsOwnerOfGroup(userID string, groupID string) (code int, msg string) {
	rows, err := myDB.QuerySql("select owner from groups where id = $1", groupID)
	if err != nil {
		return errDBQueryFailed, err.Error()
	}
	defer rows.Close()
	var owner string
	if !rows.Next() {
		return errNoPermission, "user " + userID + "is not in group " + groupID
	}
	err = rows.Scan(&owner)
	if err != nil {
		return errRowsScan, err.Error()
	}
	if userID != owner {
		return errNoPermission, "user " + userID + " is not owner of group " + groupID
	}
	return Success, ""
}

func judgeToken(Token string) (code int, msg string, userID string) {
	user, ok := token.GetUser(Token)
	if !ok {
		return errInvalidToken, "token not exist", ""
	}
	return Success, "", user.ID
}

func canAddGroupMember(groupID string, addNum int) (code int, msg string) {
	rows, err := myDB.QuerySql("select count(*) from members where groupID = $1", groupID)
	if err != nil {
		return errDBQueryFailed, err.Error()
	}
	defer rows.Close()
	var num int
	if !rows.Next() {
		return errDBQueryFailed, "rows has no next"
	}
	err = rows.Scan(&num)
	if err != nil {
		return errRowsScan, err.Error()
	}
	if num+addNum > 200 {
		return errTooManyGroupMember, "群成员不能超过200"
	}
	return Success, ""
}
